package com.car.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.car.account.controller.form.adminForm.AdminCodeLoginForm;
import com.car.account.controller.form.adminForm.AdminPassLoginForm;
import com.car.account.dto.adminDto.AdminDto;
import com.car.account.dto.adminDto.SelectAdminDto;
import com.car.account.dto.userDto.UserInfoByIdDto;
import com.car.account.dto.userDto.UserInfoDto;
import com.car.account.entity.Admin;
import com.car.account.entity.AdminRole;
import com.car.account.entity.PlatformRole;
import com.car.account.entity.User;
import com.car.account.exception.AccountException;
import com.car.account.mapper.AdminMapper;
import com.car.account.param.adminParam.InsertAdminParam;
import com.car.account.param.adminParam.SelectAdminDtoParam;
import com.car.account.param.adminParam.UpdateRoleParam;
import com.car.account.param.userParam.SelectUserInfoDtoParam;
import com.car.account.rabbitmq.SendLoginCodeConsumer;
import com.car.account.service.AdminRoleService;
import com.car.account.service.AdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.car.account.service.PlatformRoleService;
import com.car.account.service.UserService;
import com.car.account.util.ListUtil;
import com.car.account.util.PageDtoUtil;
import com.car.account.util.aliyunUtil.AliyunOssUtil;
import com.car.account.util.validatorUtil.PasswordValidator;
import com.car.account.util.validatorUtil.PhoneNumberValidator;
import com.car.commons.web.util.MD5util;
import com.car.commons.web.util.RedisKeyUtil;
import com.car.commons.web.util.RedisUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 董旭
 * @since 2024-08-28
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Resource
    private AdminService adminService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private SendLoginCodeConsumer sendLoginCodeConsumer;

    @Resource
    private UserService userService;

    @Resource
    private PlatformRoleService platformRoleService;

    @Resource
    private AdminRoleService adminRoleService;

    @Resource
    private AliyunOssUtil aliyunOssUtil;

    @Resource
    private AdminMapper adminMapper;

    @Override
    public Integer adminPassLogin(AdminPassLoginForm form) throws Exception {
        //判断是否存在平台账号
        Admin admin = adminService.getOne(new QueryWrapper<Admin>()
                .eq("admin_phone", form.getAdminPhone())
                .ne("admin_state", 2));
        if (admin == null) throw new AccountException(2000,"平台账号不存在");
        //判断状态是否正常
        if (admin.getAdminState() == 1) throw new AccountException(2001,"平台账号被禁用");
        //判断密码是否正确
        if (!MD5util.md5(form.getAdminPhone(),form.getAdminPass()).equals(admin.getAdminPass()))
            throw new AccountException(2002,"密码错误");
        return admin.getAdminId();
    }

    @Override
    public void sendAdminLoginCode(String adminPhone) throws Exception {
        //判断是否存在平台账号
        Admin admin = adminService.getOne(new QueryWrapper<Admin>()
                .eq("admin_phone", adminPhone)
                .ne("admin_state", 2));
        if (admin == null) throw new AccountException(2000,"平台账号不存在");
        //判断状态是否正常
        if (admin.getAdminState() == 1) throw new AccountException(2001,"平台账号被禁用");
        //判断一分钟内重复发送
        if (redisUtil.hasKey(RedisKeyUtil.loginCodeOnMinute(adminPhone)))
            throw new AccountException(2002,"请勿在1分钟内重复发送");
        //判断一小时内发送次数
        if (!redisUtil.hasKey(RedisKeyUtil.sendNumbers(adminPhone))) {
            redisUtil.set(RedisKeyUtil.sendNumbers(adminPhone), "1", 60*60);
        }
        String num = redisUtil.get(RedisKeyUtil.sendNumbers(adminPhone));
        if (!num.isEmpty() && Integer.parseInt(num) >= 5) {
            throw new AccountException(1004,"一小时内发送验证码超出5条，稍后再试");
        }
        sendLoginCodeConsumer.sendLoginCode(adminPhone);
    }

    @Override
    public Integer adminCodeLogin(AdminCodeLoginForm form) throws Exception {
        //判断是否存在平台账号
        Admin admin = adminService.getOne(new QueryWrapper<Admin>()
                .eq("admin_phone", form.getAdminPhone())
                .ne("admin_state", 2));
        if (admin == null) throw new AccountException(2000,"平台账号不存在");
        //判断状态是否正常
        if (admin.getAdminState() == 1) throw new AccountException(2001,"平台账号被禁用");
        //验证验证码
        if (!redisUtil.hasKey(RedisKeyUtil.loginCodeKey(form.getAdminPhone())))
            throw new AccountException(1005,"无效验证码");
        String code = redisUtil.get(RedisKeyUtil.loginCodeKey(form.getAdminPhone()));
        if (!code.equals(form.getCode()))
            throw new AccountException(1006,"验证码有误");
        //删除redis验证码
        redisUtil.del(RedisKeyUtil.loginCodeKey(form.getAdminPhone()));
        return admin.getAdminId();
    }

    @Override
    @Transactional
    public void disableUserByUserId(Integer adminId, Integer userId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(2003,"用户不存在");
        //判断用户状态
        if (user.getUserState() == 1) throw new AccountException(2004,"用户已经是禁用状态");
        //修改为禁用状态
        user.setUserState(1);
        userService.updateById(user);
    }

    @Override
    @Transactional
    public void enableUserByUserId(Integer adminId, Integer userId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(2003,"用户不存在");
        //判断用户状态
        if (user.getUserState() == 0) throw new AccountException(2004,"用户已经是启用状态");
        //修改为禁用状态
        user.setUserState(0);
        userService.updateById(user);
    }

    @Override
    @Transactional
    public void deleteUserByUserId(Integer adminId, Integer userId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(2003,"用户不存在");
        //删除用户
        user.setUserState(2);
        userService.updateById(user);
    }

    @Override
    @Transactional
    public void silenceUserByUserId(Integer adminId, Integer userId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(2003,"用户不存在");
        //判断用户状态
        if (user.getUserState() == 1) throw new AccountException(2004,"用户是禁用状态");
        //判断用户禁言状态
        if (user.getSilenceState() == 1) throw new AccountException(2005,"用户已经是禁言状态");
        //修改禁言状态
        user.setSilenceState(1);
        userService.updateById(user);
    }

    @Override
    @Transactional
    public void unbanUserByUserId(Integer adminId, Integer userId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(2003,"用户不存在");
        //判断用户状态
        if (user.getUserState() == 1) throw new AccountException(2004,"用户是禁用状态");
        //判断用户禁言状态
        if (user.getSilenceState() == 0) throw new AccountException(2005,"用户已经是非禁言状态");
        //修改禁言状态
        user.setSilenceState(0);
        userService.updateById(user);
    }

    @Override
    public UserInfoByIdDto adminSelectUserInfoDtoById(Integer adminId, Integer userId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(2003,"用户不存在");
        UserInfoByIdDto userInfoByIdDto = BeanUtil.toBean(user, UserInfoByIdDto.class);
        return userInfoByIdDto;
    }

    @Override
    public Page<UserInfoDto> adminSelectUserInfoDto(SelectUserInfoDtoParam param) throws Exception {
        //验证手机号格式
        if (!param.getUserPhone().isEmpty()) {
            if (!PhoneNumberValidator.isValidPhoneNumber(param.getUserPhone()))
                throw new AccountException(2001,"手机号格式不正确");
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper
                .like("user_name", param.getUserName())
                .like("user_phone", param.getUserPhone())
                .ne("user_state", 2);
        Page<User> page = new Page<>(param.getCurrent()==null?1:param.getCurrent(), param.getSize()==null?6:param.getSize());
        Page<User> userPage = userService.page(page, userQueryWrapper);
        Page<UserInfoDto> userInfoDtoPage = PageDtoUtil.convertPage(userPage, UserInfoDto.class);
        return userInfoDtoPage;
    }

    @Override
    @Transactional
    public void updateAdminPhoneById(Integer adminId, String adminPhone) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断手机号是否被绑定
        Admin adminByPhone = getOne(new QueryWrapper<Admin>()
                .eq("admin_phone", adminPhone)
                .ne("admin_state", 2));
        if (adminByPhone != null) throw new AccountException(2003,"手机号已被绑定");
        admin.setAdminPhone(adminPhone);
        updateById(admin);
    }

    @Override
    @Transactional
    public void updateAdminPassById(Integer adminId, String adminPass) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断密码格式
        if (!PasswordValidator.isValidPassword(adminPass)) throw new AccountException(2003,"密码格式不正确");
        //修改密码
        admin.setAdminPass(MD5util.md5(admin.getAdminPhone(),adminPass));
        updateById(admin);
    }

    @Override
    @Transactional
    public String adminUpdateImage(MultipartFile mf, Integer adminId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        String imageName = aliyunOssUtil.upImage(mf);
        admin.setImage(imageName);
        updateById(admin);
        return imageName;
    }

    @Override
    public List<PlatformRole> selectAdminRole(Integer adminId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        List<PlatformRole> roles = platformRoleService.list();
        return roles;
    }

    @Override
    @Transactional
    public void insertAdmin(InsertAdminParam param) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(param.getAdminId());
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        PlatformRole role = platformRoleService.getById(param.getRoleId());
        if (role == null) throw new AccountException(2003,"身份信息有误");
        //判断手机号是否被绑定
        Admin adminByPhone = getOne(new QueryWrapper<Admin>()
                .eq("admin_phone", param.getAdminPhone())
                .ne("admin_state", 2));
        if (adminByPhone != null) throw new AccountException(2004,"手机号已被绑定");
        //判断手机号格式
        if (!PhoneNumberValidator.isValidPhoneNumber(param.getAdminPhone()))
            throw new AccountException(2005,"手机号格式有误");
        //添加管理员
        Admin admin = new Admin();
        admin.setAdminName(param.getAdminName());
        admin.setAdminPhone(param.getAdminPhone());
        admin.setAdminPass(MD5util.md5(param.getAdminPhone(),"123456"));
        admin.setImage("https://superman-book.oss-cn-chengdu.aliyuncs.com/%E7%94%A8%E6%88%B7%E9%BB%98%E8%AE%A4%E5%A4%B4%E5%83%8F.png");
        admin.setAdminState(0);
        boolean isSave = save(admin);
        //添加管理员身份数据
        if (isSave) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getAdminId());
            adminRole.setRoleId(param.getRoleId());
            adminRoleService.save(adminRole);
        }else  throw new AccountException(2006,"添加失败");
    }

    @Override
    @Transactional
    public void disableAdmin(Integer currentAdminId, Integer adminId) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(currentAdminId);
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2003,"平台账号不存在");
        //判断是否属于自己的账号
        if (currentAdminId == adminId) throw new AccountException(2004,"不可操作当前账号");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2005,"平台账号已经是禁用状态");
        admin.setAdminState(1);
        updateById(admin);
    }

    @Override
    public void enableAdmin(Integer currentAdminId, Integer adminId) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(currentAdminId);
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2003,"平台账号不存在");
        //判断是否属于自己的账号
        if (currentAdminId == adminId) throw new AccountException(2004,"不可操作当前账号");
        //判断平台账号状态
        if (admin.getAdminState() == 0) throw new AccountException(2005,"平台账号已经是解禁状态");
        admin.setAdminState(0);
        updateById(admin);
    }

    @Override
    public void deleteAdmin(Integer currentAdminId, Integer adminId) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(currentAdminId);
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2003,"平台账号不存在");
        //判断是否属于自己的账号
        if (currentAdminId == adminId) throw new AccountException(2004,"不可操作当前账号");
        admin.setAdminState(2);
        updateById(admin);
    }

    @Override
    public AdminDto selectAdminDto(Integer adminId) throws Exception {
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2001,"平台账号不存在");
        //判断平台账号状态
        if (admin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        AdminDto adminDto = BeanUtil.toBean(admin, AdminDto.class);
        return adminDto;
    }

    @Override
    public Page<SelectAdminDto> selectAdmins(SelectAdminDtoParam param) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(param.getCurrentAdminId());
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //开启分页
        Page<SelectAdminDto> page = new Page<>(param.getCurrent() == null ? 1 : param.getCurrent(), param.getSize() == null ? 6 : param.getSize());
        return adminMapper.findAdminInfo(page, param.getAdminName(), param.getAdminPhone());
    }

    @Override
    public List<SelectAdminDto> findsAdminByIds(Integer currentAdminId, Set<Integer> adminIds) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(currentAdminId);
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        List<Admin> admins = list(new QueryWrapper<Admin>().in("admin_id", adminIds));
        return ListUtil.copyToList(admins, SelectAdminDto.class);
    }

    @Override
    public Integer selectAdminAllRole(Integer currentAdminId, Integer adminId) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(currentAdminId);
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在平台账号
        Admin admin = getById(adminId);
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2003,"平台账号不存在");
        //判断是否属于自己的账号
        if (currentAdminId == adminId) throw new AccountException(2004,"不可操作当前账号");
        //判断状态
        if (admin.getAdminState() == 1) throw new AccountException(2005,"账号是禁用状态");
        AdminRole adminRole = adminRoleService.getOne(new QueryWrapper<AdminRole>().eq("admin_id", admin.getAdminId()));
        return adminRole.getRoleId();
    }

    @Override
    @Transactional
    public void updateAdminRole(UpdateRoleParam param) throws Exception {
        //判断是否存在当前平台账号
        Admin currentAdmin = getById(param.getCurrentAdminId());
        if (currentAdmin == null || currentAdmin.getAdminState() == 2)
            throw new AccountException(2001,"平台账号不存在");
        //判断当前平台账号状态
        if (currentAdmin.getAdminState() == 1) throw new AccountException(2002,"平台账号已被禁用");
        //判断是否存在平台账号
        Admin admin = getById(param.getAdminId());
        if (admin == null || admin.getAdminState() == 2) throw new AccountException(2003,"平台账号不存在");
        //判断是否属于自己的账号
        if (param.getCurrentAdminId() == param.getAdminId()) throw new AccountException(2004,"不可操作当前账号");
        //判断状态
        if (admin.getAdminState() == 1) throw new AccountException(2005,"账号是禁用状态");
        //删除曾经身份
        adminRoleService.remove(new QueryWrapper<AdminRole>()
                .eq("admin_id", admin.getAdminId()));
        //创建新身份
        AdminRole adminRole = new AdminRole();
        adminRole.setRoleId(param.getRoleId());
        adminRole.setAdminId(param.getAdminId());
        adminRoleService.save(adminRole);
    }

}
